<template>
  <div class="graphic-code" @click="loadGraphic" ref="graphicCode" :style="currentStyle">
    <img class="graphic-code-canvas" :src="remoteImg" v-if="remote" />
    <canvas class="graphic-code-canvas" v-else :width="width" :height="height"></canvas>
  </div>
</template>

<script>
export default {
  name: 'GraphicCode',
  props: {
    remote: {
      type: Boolean,
      default: false,
    },
    length: {
      type: Number,
      default: 4,
    },
    width: {
      type: Number,
      default: 140,
    },
    height: {
      type: Number,
      default: 36,
    },
    fontSizeMin: {
      type: Number,
      default: 20,
    },
    fontSizeMax: {
      type: Number,
      default: 45,
    },
    backgroundColorMin: {
      type: Number,
      default: 180,
    },
    backgroundColorMax: {
      type: Number,
      default: 240,
    },
    colorMin: {
      type: Number,
      default: 50,
    },
    colorMax: {
      type: Number,
      default: 160,
    },
    lineColorMin: {
      type: Number,
      default: 40,
    },
    lineColorMax: {
      type: Number,
      default: 180,
    },
    dotColorMin: {
      type: Number,
      default: 0,
    },
    dotColorMax: {
      type: Number,
      default: 255,
    },
  },
  data() {
    return {
      remoteImg: '',
      localCode: '',
    };
  },

  computed: {
    currentStyle() {
      const { width, height } = this;

      return {
        width: `${width}px`,
        height: `${height}px`,
      };
    },
  },

  methods: {
    // 外部调用检查 localcode
    check(val) {
      return val.toLowerCase() === this.localCode.toLowerCase();
    },

    // 加载图片
    loadGraphic() {
      const { remote } = this;

      // 远程获取 base64 图片
      if (remote) {
        this.$api.user.getGraphicCode().then(({ data }) => {
          this.remoteImg = data;
        });
      } else {
        this.drawLocalCode();
      }
    },

    drawLocalCode() {
      this.randomLocalCode();
      this.drawGraphic();
    },

    drawGraphic() {
      let canvas = this.$refs.graphicCode.querySelector('.graphic-code-canvas');
      let ctx = canvas.getContext('2d');
      ctx.textBaseline = 'bottom';
      // 绘制背景
      ctx.fillStyle = this.randomColor(this.backgroundColorMin, this.backgroundColorMax);
      ctx.fillRect(0, 0, this.width, this.height);
      // 绘制文字
      for (let i = 0; i < this.localCode.length; i++) {
        this.drawText(ctx, this.localCode[i], i);
      }
      this.drawLine(ctx);
      this.drawDot(ctx);
    },
    drawText(ctx, txt, i) {
      ctx.fillStyle = this.randomColor(this.colorMin, this.colorMax);
      let fontSize = this.randomNum(this.fontSizeMin, this.fontSizeMax);
      ctx.font = fontSize + 'px SimHei';
      let padding = 5;
      let offset = (this.width - 10) / this.localCode.length;
      let x = padding;
      if (i > 0) {
        x = padding + i * offset;
      }
      //let x = (i + 1) * (this.width / (this.localCode.length + 1))
      let y = this.randomNum((this.fontSizeMin + this.fontSizeMax) / 2, this.height - 5);
      if (fontSize > 40) {
        y = 40;
      }
      const deg = this.randomNum(-10, 10);
      // 修改坐标原点和旋转角度
      ctx.translate(x, y);
      ctx.rotate((deg * Math.PI) / 180);
      ctx.fillText(txt, 0, 0);
      // 恢复坐标原点和旋转角度
      ctx.rotate((-deg * Math.PI) / 180);
      ctx.translate(-x, -y);
    },
    drawLine(ctx) {
      // 绘制干扰线
      for (let i = 0; i < 1; i++) {
        ctx.strokeStyle = this.randomColor(this.lineColorMin, this.lineColorMax);
        ctx.beginPath();
        ctx.moveTo(this.randomNum(0, this.width), this.randomNum(0, this.height));
        ctx.lineTo(this.randomNum(0, this.width), this.randomNum(0, this.height));
        ctx.stroke();
      }
    },
    drawDot(ctx) {
      // 绘制干扰点
      for (let i = 0; i < 100; i++) {
        ctx.fillStyle = this.randomColor(0, 255);
        ctx.beginPath();
        ctx.arc(this.randomNum(0, this.width), this.randomNum(0, this.height), 1, 0, 2 * Math.PI);
        ctx.fill();
      }
    },

    // 生成一个随机数
    randomNum(min, max) {
      return Math.floor(Math.random() * (max - min) + min);
    },
    // 生成一个随机的颜色
    randomColor(min, max) {
      let r = this.randomNum(min, max);
      let g = this.randomNum(min, max);
      let b = this.randomNum(min, max);
      return 'rgb(' + r + ',' + g + ',' + b + ')';
    },

    // 生成随机 code
    randomLocalCode() {
      let random = '';
      //去掉了I l i o O
      let str = 'QWERTYUPLKJHGFDSAZXCVBNMqwertyupkjhgfdsazxcvbnm1234567890';
      for (let i = 0; i < this.length; i++) {
        let index = Math.floor(Math.random() * 57);
        random += str[index];
      }
      this.localCode = random;
    },
  },

  mounted() {
    this.loadGraphic();
  },
};
</script>

<style lang="scss" scoped>
.graphic-code {
  cursor: poiner;

  &-canvas {
    display: block;
    width: 100%;
    height: 100%;
  }
}
</style>
